//////////////////////////////////////////////////////////////////////
//
// Experiment0:  10 uncoupled neurons with random initial potentials
//
//////////////////////////////////////////////////////////////////////

import java.util.LinkedList ;
import java.awt.Color ;

public class Experiment0 extends ParameterFramework implements INeuralNetExperiment {
    private INeuron baseNeuron = null ;
    private ISynapse baseSynapse = null ;
    private INeuron [ ] n = null ;
    private int NUM_NEURONS = 10 ;
    private int runTime = 20 ;
    private IAppliedCurrent Iapp ;
    
    public Experiment0( IAppliedCurrent Iapp ) {
        init( Iapp ) ;
    }
    
    public INeuralNetExperiment clone( ) {
        Experiment0 c = new Experiment0( Iapp ) ;
        c.setParam( getParams( ) ) ;
        return c ;
    }
    
    
    private void init( IAppliedCurrent Iapp ) {
        String [ ] params = { "numNeurons" , "runTime" } ;
        this.Iapp = Iapp ;
        parameterNames = params ;
    }
    
    public Experiment0( ) {
        init( new ConstantCurrent( 0 ) ) ;
    }
    
    public void setCurrent( IAppliedCurrent Iapp ) {
        this.Iapp = Iapp ;
    }
    
    public String getName( ) {
        return "Uncoupled Neurons" ;
    }
    
    public String getParam( String name ) {
        if ( name.equals( "numNeurons" ) ) {
            return "" + NUM_NEURONS ;
        } else if ( name.equals( "runTime" ) ) {
            return "" + runTime ;
        } else {
            return null ;
        }
    }
    
    public void setParam( String name , String data ) {
        double value ;
        
        // all parameters are integers
        try {
            value = Double.parseDouble( data ) ;
        } catch ( NumberFormatException e ) {
            // not a double; ignore the set request
            return ;
        }
        
        if ( name.equals( "numNeurons" ) ) {
            NUM_NEURONS = ( int ) Math.round( value ) ;
        } else if ( name.equals( "runTime" ) ) {
            runTime = ( int ) Math.round( value ) ;
        }
    }
    
    public void init( INeuron n , ISynapse s ) {
        baseNeuron = n ;
        baseSynapse = s ;
    }
    
    public LinkedList<INeuron> getNeurons( ) {
        LinkedList<INeuron> result = new LinkedList<INeuron> ( ) ;
        int i ;
        for ( i = 0 ; i < n.length ; i ++ ) {
            result.add( n [ i ] ) ;
        }
        
        return result ;
    }
    
    public void run( ) {
        int i , j ;
        
        if ( baseNeuron == null ) return ;
        
        // clone the neurons
        n = new INeuron [ NUM_NEURONS ] ;
        for ( j = 0 ; j < NUM_NEURONS ; j ++ ) {
            n [ j ] = baseNeuron.clone( ) ;
            n[j].setTime( 0 ) ;
            n[j].setPotential( Math.random( ) - .4 ) ;
            n[j].setAppliedCurrent( Iapp ) ;
        }
        
        // run
        for ( i = 0 ; i < runTime ; i ++ ) {
            for ( j = 0 ; j < NUM_NEURONS ; j ++ ) {
                n[j].advance( ) ;
            }
        }
    }
    
    private Curve appliedCurrentCurve( int tStart , int tStop ) {
        int i ;
        OrderedPair [ ] pts = new OrderedPair [ tStop - tStart ] ;
        Curve result ;
        
        for ( i = tStart ; i < tStop ; i ++ ) {
            pts [ i - tStart ] = new OrderedPair( i , Iapp.amount( i ) ) ;
        }
        result = new Curve( pts , "Iapp" ) ;
        result.setColor( Color.BLUE ) ;
        return result ;
    }
    
    
    
    public LinkedList<Curve> getCurves( ) {
        return getCurves( 0 , n[0].getTime( ) ) ;
    }
    
    public LinkedList<Curve> getCurves( int tStart , int tStop ) {
        LinkedList<Curve> result = new LinkedList<Curve> ( ) ;
        int j ;
        Curve c ;
        
        if ( n == null ) return result ;
        
        // add a curve for the applied current
        result.add( appliedCurrentCurve( tStart , tStop ) ) ;
        
        // loop through the neurons, add each curve
        for ( j = 0 ; j < NUM_NEURONS ; j ++ ) {
            c = n[j].getCurve( tStart , tStop ) ;
            c.id = "" + ( j + 1 ) ;
            result.add( c ) ;
        }
        
        return result ;
    }
    
}
